#include "VideoUI.h"
#include "lvgl/lvgl.h"
#include <stdlib.h>
#include "sys.h"

#define TOPCONT_HIGHT 35
#define PLAY_WINDOW_BOTTOM_CONT_HEIGHT 80

struct PlayWindow
{
  lv_obj_t *screen;
  lv_obj_t *bottomCont;
  lv_obj_t *pauseImage;
  lv_obj_t *listImage;
  lv_obj_t *progSlider;
  lv_obj_t *videoLabel;
  lv_obj_t *timeLabel;
  lv_obj_t *volumeSlider;
};

LV_IMG_DECLARE(butterfly)
LV_IMG_DECLARE(list)
LV_IMG_DECLARE(pause_icon)
LV_IMG_DECLARE(playing)
LV_IMG_DECLARE(item_idle)
LV_IMG_DECLARE(item_playing)
LV_IMG_DECLARE(volume)

static lv_ft_info_t font16;
static lv_ft_info_t font18;
static lv_ft_info_t font25;
static lv_ft_info_t font30;

static void drag_event_handler(lv_event_t *e);
static void videoList_btn_event_cb(lv_event_t *e);
static void play_window_bottom_pause_btn_click_event_cb(lv_event_t *e);
static void play_window_bottom_list_btn_click_event_cb(lv_event_t *e);
static void video_progress_slider_event_cb(lv_event_t *e);
static void volume_slider_event_cb(lv_event_t *e);
static void screen_click_event_handler(lv_event_t *e);
static void transp_bottom_cont_timer_cb(lv_timer_t *t);

// gui回调函数集
static VideoUI::Operations uiOpts;

// LCD分辨率
static uint32_t lcdW = 480;
static uint32_t lcdH = 272;

// 背景图片
static lv_obj_t *backImage;

// 退出按钮
static lv_obj_t *exitBtn;

// 视频列表顶部容器
static lv_obj_t *topCont;

// 视频列表list
static lv_obj_t *videoList;

// 保存当前正在播放的视频对应的list btn
static lv_obj_t *playingVideoBtn = nullptr;

// 播放视频窗口
static PlayWindow playWindow;

// 播放进度slider是否被按下
static bool videoSliderPressed = false;

// 清屏定时器
static lv_timer_t *clearScreenTimer = nullptr;

/**
 *@brief 初始化界面UI
 *@param opts UI回调函数集合
 */
void VideoUI::create(Operations &opts)
{
  lv_obj_t *act = lv_scr_act();

  uiOpts = opts;

  // 初始化字体
  font16.name = SystemFontFile;
  font16.weight = 16;
  font16.style = FT_FONT_STYLE_NORMAL;
  font16.mem = nullptr;
  lv_ft_font_init(&font16);

  font18.name = SystemFontFile;
  font18.weight = 18;
  font18.style = FT_FONT_STYLE_NORMAL;
  font18.mem = nullptr;
  lv_ft_font_init(&font18);

  font25.name = SystemFontFile;
  font25.weight = 25;
  font25.style = FT_FONT_STYLE_NORMAL;
  font25.mem = nullptr;
  lv_ft_font_init(&font25);

  font30.name = SystemFontFile;
  font30.weight = 30;
  font30.style = FT_FONT_STYLE_NORMAL;
  font30.mem = nullptr;
  lv_ft_font_init(&font30);

  // 获取显示设备分辨率
  lcdW = lv_disp_get_hor_res(nullptr);
  lcdH = lv_disp_get_ver_res(nullptr);

  // 创建背景图片
  backImage = lv_img_create(act);
  lv_img_set_src(backImage, "S:./res/background/videobg.bin");
  lv_obj_set_size(backImage, lcdW, lcdH);
  lv_obj_clear_flag(backImage, LV_OBJ_FLAG_SCROLLABLE);
  lv_obj_set_style_bg_color(backImage, lv_color_hex(0x000000), LV_STATE_DEFAULT);

  // 创建视频列表顶部容器
  topCont = lv_obj_create(backImage);
  lv_obj_set_size(topCont, lcdW, TOPCONT_HIGHT);
  lv_obj_clear_flag(topCont, LV_OBJ_FLAG_SCROLLABLE);
  lv_obj_set_style_bg_color(topCont, lv_color_hex(0x000000), LV_STATE_DEFAULT);
  lv_obj_set_style_bg_opa(topCont, LV_OPA_30, LV_STATE_DEFAULT);
  lv_obj_set_style_border_width(topCont, 0, LV_STATE_DEFAULT);
  lv_obj_set_style_pad_all(topCont, 0, LV_STATE_DEFAULT);
  lv_obj_set_style_radius(topCont, 0, LV_STATE_DEFAULT);

  lv_obj_t *title_label = lv_label_create(topCont);
  lv_obj_set_style_text_font(title_label, font30.font, LV_STATE_DEFAULT);
  lv_obj_set_style_text_color(title_label, lv_color_hex(0xeaeaea), LV_STATE_DEFAULT);
  lv_label_set_text(title_label, "视频播放器");
  lv_obj_center(title_label);

  // 创建视频列表list
  videoList = lv_list_create(backImage);
  lv_obj_set_size(videoList, lcdW, lcdH - TOPCONT_HIGHT);
  lv_obj_align_to(videoList, topCont, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
  lv_obj_set_style_bg_opa(videoList, LV_OPA_TRANSP, LV_STATE_DEFAULT);      // 设置背景透明度
  lv_obj_set_style_bg_color(videoList, lv_color_black(), LV_STATE_DEFAULT); // 背景黑色
  lv_obj_set_style_border_opa(videoList, LV_OPA_TRANSP, LV_STATE_DEFAULT);  // 设置边框透明
  lv_obj_set_style_radius(videoList, 0, LV_STATE_DEFAULT);                  // 边框圆角为0

  // 创建退出按钮
  exitBtn = lv_obj_create(backImage);
  lv_obj_set_size(exitBtn, 70, 70);
  lv_obj_set_pos(exitBtn, 935, 267);
  lv_obj_clear_flag(exitBtn, LV_OBJ_FLAG_SCROLLABLE); // 禁止滚动
  lv_obj_set_style_radius(exitBtn, 35, LV_STATE_DEFAULT);
  lv_obj_set_style_bg_color(exitBtn, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
  lv_obj_set_style_border_opa(exitBtn, LV_OPA_TRANSP, LV_STATE_DEFAULT); // A边框透明
  lv_obj_set_style_bg_opa(exitBtn, LV_OPA_50, LV_STATE_DEFAULT);
  lv_obj_set_style_bg_opa(exitBtn, LV_OPA_90, LV_STATE_PRESSED);

  lv_obj_t *img = lv_img_create(exitBtn);
  lv_img_set_src(img, &butterfly);
  lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
  lv_obj_add_flag(img, LV_OBJ_FLAG_EVENT_BUBBLE);

  lv_obj_add_event_cb(exitBtn, drag_event_handler, LV_EVENT_PRESSING, nullptr);
  if (uiOpts.exitCb != nullptr)
    lv_obj_add_event_cb(
        exitBtn,
        [](lv_event_t *e)
        {
          uiOpts.exitCb();
        },
        LV_EVENT_SHORT_CLICKED, nullptr);
}

/**
 *@brief 添加一个视频到列表
 *@param name 视频文件名称
 */
void VideoUI::addVideoList(const char *name)
{
  // 添加一个按钮到list
  lv_obj_t *btn = lv_list_add_btn(videoList, &item_idle, name);
  lv_obj_set_flex_align(btn, (lv_flex_align_t)LV_FLEX_FLOW_ROW, LV_FLEX_ALIGN_CENTER, (lv_flex_align_t)LV_FLEX_FLOW_ROW);
  lv_obj_set_style_bg_opa(btn, LV_OPA_TRANSP, LV_STATE_DEFAULT); // 设置背景透明
  lv_obj_set_style_bg_opa(btn, LV_OPA_30, LV_STATE_PRESSED);     // 设置背景透明度(按下时)
  lv_obj_set_style_text_color(btn, lv_color_hex(0x82cef5), LV_STATE_DEFAULT);
  lv_obj_set_style_text_font(btn, font25.font, LV_STATE_DEFAULT); // 设置字体
  lv_obj_add_event_cb(btn, videoList_btn_event_cb, LV_EVENT_SHORT_CLICKED, nullptr);

  int len = strlen(name) + 1;
  char *video_name = new char[len];
  strcpy(video_name, name);

  lv_obj_set_user_data(btn, video_name);
}

/**
 *@brief 创建播放窗口
 */
static void uiCreatePlayWindow(void)
{
  lv_disp_get_default()->driver->screen_transp = 1;
  lv_disp_set_bg_opa(lv_disp_get_default(), LV_OPA_TRANSP); // 设置屏幕透明
  lv_memset_00(lv_disp_get_default()->driver->draw_buf->buf_act,
               lv_disp_get_default()->driver->draw_buf->size * sizeof(lv_color32_t)); // 清空屏幕
  lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_TRANSP, LV_STATE_DEFAULT);             // 背景透明

  lv_obj_set_style_opa(backImage, LV_OPA_TRANSP, LV_STATE_DEFAULT); // 视频列表透明

  // 创建幕布
  lv_obj_t *screen = lv_obj_create(lv_scr_act());
  lv_obj_set_size(screen, lcdW, lcdH);
  lv_obj_set_style_bg_opa(screen, LV_OPA_TRANSP, LV_STATE_DEFAULT); // 幕布背景透明
  lv_obj_set_style_border_width(screen, 0, LV_STATE_DEFAULT);       // 幕布边框为0
  lv_obj_set_style_pad_all(screen, 0, LV_STATE_DEFAULT);            // 幕布填充为0
  lv_obj_add_flag(screen, LV_OBJ_FLAG_CLICKABLE);                   // 可点击
  lv_obj_add_event_cb(screen, screen_click_event_handler, LV_EVENT_CLICKED, nullptr);
  playWindow.screen = screen;

  // 创建底部容器
  lv_obj_t *cont = lv_obj_create(screen);
  lv_obj_set_size(cont, lcdW, PLAY_WINDOW_BOTTOM_CONT_HEIGHT);
  lv_obj_align(cont, LV_ALIGN_BOTTOM_MID, 0, 0);
  lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE); // 禁止滚动
  lv_obj_set_style_radius(cont, 0, LV_STATE_DEFAULT);
  lv_obj_set_style_border_width(cont, 0, LV_STATE_DEFAULT);                  // 无边框
  lv_obj_set_style_bg_color(cont, lv_color_hex(0x000000), LV_STATE_DEFAULT); // 背景黑色
  lv_obj_set_style_opa(cont, LV_OPA_TRANSP, LV_STATE_DEFAULT);               // 透明
  playWindow.bottomCont = cont;

  // 创建底部暂停播放
  do
  {
    const lv_img_dsc_t *icon[] = {&playing, &list};
    lv_obj_t **imgs[] = {&playWindow.pauseImage, &playWindow.listImage};
    lv_event_cb_t img_cbs[] =
        {
            play_window_bottom_pause_btn_click_event_cb,
            play_window_bottom_list_btn_click_event_cb,
        };

    for (int i = 0; i < sizeof(icon) / sizeof(icon[0]); i++) // 创建5img按钮
    {
      imgs[i][0] = lv_img_create(cont); // img按钮
      lv_img_set_src(imgs[i][0], icon[i]);
      lv_obj_set_style_img_opa(imgs[i][0], LV_OPA_60, LV_STATE_DEFAULT);    // 松开时透明度
      lv_obj_set_style_img_opa(imgs[i][0], LV_OPA_COVER, LV_STATE_PRESSED); // 按下时透明度
      lv_obj_add_flag(imgs[i][0], LV_OBJ_FLAG_CLICKABLE);
      lv_obj_add_event_cb(imgs[i][0], img_cbs[i], LV_EVENT_SHORT_CLICKED, nullptr);

      if (i != 0)
        lv_obj_align_to(imgs[i][0], imgs[i - 1][0], LV_ALIGN_OUT_RIGHT_MID, 10, 0);
      else
        lv_obj_align(imgs[i][0], LV_ALIGN_LEFT_MID, 0, 0);
    }
  } while (0);

  // 创建视频进度滑块条
  lv_obj_t *slider = lv_slider_create(cont);
  lv_obj_set_size(slider, 500, 10);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0xe6e6e6), LV_STATE_DEFAULT);
  lv_obj_set_style_bg_opa(slider, LV_OPA_60, LV_STATE_DEFAULT);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0x82cef5), LV_PART_INDICATOR | LV_STATE_DEFAULT);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0x82cef5), LV_PART_KNOB | LV_STATE_DEFAULT);
  lv_obj_align_to(slider, playWindow.listImage, LV_ALIGN_OUT_RIGHT_MID, 15, 0);
  lv_obj_add_event_cb(slider, video_progress_slider_event_cb, LV_EVENT_RELEASED, nullptr);
  lv_obj_add_event_cb(slider, video_progress_slider_event_cb, LV_EVENT_PRESSING, nullptr);
  lv_obj_add_event_cb(slider, video_progress_slider_event_cb, LV_EVENT_PRESSED, nullptr);
  playWindow.progSlider = slider;

  // 创建视频文件名标签
  lv_obj_t *videoNameLabel = lv_label_create(cont);
  lv_obj_set_style_text_font(videoNameLabel, font18.font, LV_STATE_DEFAULT);
  lv_obj_set_style_text_color(videoNameLabel, lv_color_hex(0xe6e6e6), LV_STATE_DEFAULT);
  lv_label_set_text(videoNameLabel, "无视频播放");
  lv_obj_align_to(videoNameLabel, slider, LV_ALIGN_OUT_TOP_LEFT, 0, -5);
  playWindow.videoLabel = videoNameLabel;

  // 创建视频进度时间标签
  lv_obj_t *timeLabel = lv_label_create(cont);
  lv_obj_set_style_text_font(timeLabel, font16.font, LV_STATE_DEFAULT);
  lv_obj_set_style_text_color(timeLabel, lv_color_hex(0xe6e6e6), LV_STATE_DEFAULT);
  lv_label_set_text(timeLabel, "00:00/00:00");
  lv_obj_set_user_data(slider, timeLabel);
  lv_obj_align_to(timeLabel, slider, LV_ALIGN_OUT_RIGHT_MID, 15, 0);
  playWindow.timeLabel = timeLabel;

  // 创建视频音量标签
  lv_obj_t *volumeImg = lv_img_create(cont);
  lv_img_set_src(volumeImg, &volume);
  lv_obj_align_to(volumeImg, timeLabel, LV_ALIGN_OUT_RIGHT_MID, 10, 0);

  // 创建视频音量滑块条
  slider = lv_slider_create(cont);
  lv_slider_set_range(slider, 0, 40);
  lv_obj_set_size(slider, 150, 10);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0xe6e6e6), LV_STATE_DEFAULT);
  lv_obj_set_style_bg_opa(slider, LV_OPA_60, LV_STATE_DEFAULT);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0x82cef5), LV_PART_INDICATOR | LV_STATE_DEFAULT);
  lv_obj_set_style_bg_color(slider, lv_color_hex(0x82cef5), LV_PART_KNOB | LV_STATE_DEFAULT);
  lv_obj_align_to(slider, playWindow.listImage, LV_ALIGN_OUT_RIGHT_MID, 15, 0);
  lv_obj_add_event_cb(slider, volume_slider_event_cb, LV_EVENT_RELEASED, nullptr);
  lv_obj_add_event_cb(slider, volume_slider_event_cb, LV_EVENT_PRESSING, nullptr);
  lv_obj_align_to(slider, volumeImg, LV_ALIGN_OUT_RIGHT_MID, 10, 0);
  playWindow.volumeSlider = slider;

  int volumeCur = 0;

  if (uiOpts.getVolumeCb != nullptr)
    volumeCur = uiOpts.getVolumeCb();

  lv_slider_set_value(slider, volumeCur, LV_ANIM_OFF);
}

/**
 *@brief 设置视频播放进度显示
 */
void VideoUI::setPlayProgress(int cur, int total)
{
  if (playWindow.screen == nullptr) // 还未开始播放
    return;

  lv_slider_set_range(playWindow.progSlider, 0, total);
  if (videoSliderPressed != true) // 未按下时设置
    lv_slider_set_value(playWindow.progSlider, cur, LV_ANIM_OFF);

  lv_label_set_text_fmt(playWindow.timeLabel, "%d:%d/%d:%d", cur / 60, cur % 60, total / 60, total % 60);
}

/**
 *@brief 释放播放窗口
 */
static void uiDelPlayWindow(void)
{
  lv_obj_del_async(playWindow.screen); // 删除幕布
  playWindow.screen = nullptr;
  lv_obj_set_style_opa(backImage, LV_OPA_COVER, LV_STATE_DEFAULT); // 恢复视频列表显示
}

/**
 *@brief 释放界面UI
 */
void VideoUI::release(void)
{
  lv_obj_t *btn = nullptr;

  while ((btn = lv_obj_get_child(videoList, -1)) != nullptr)
  {
    char *video_name = (char *)lv_obj_get_user_data(btn);
    if (video_name != nullptr)
      delete[] video_name;

    lv_obj_del(btn);
  }

  lv_obj_del(backImage);

  lv_ft_font_destroy(font16.font);
  lv_ft_font_destroy(font18.font);
  lv_ft_font_destroy(font25.font);
  lv_ft_font_destroy(font30.font);
}

/**
 *@brief 长按拖动控件事件函数
 */
static void drag_event_handler(lv_event_t *e)
{
  lv_obj_t *obj = lv_event_get_target(e);

  lv_indev_t *indev = lv_indev_get_act();
  if (indev == nullptr)
    return;

  lv_point_t vect;
  lv_indev_get_vect(indev, &vect);

  lv_coord_t x = lv_obj_get_x(obj) + vect.x;
  lv_coord_t y = lv_obj_get_y(obj) + vect.y;
  lv_obj_set_pos(obj, x, y);
}

/**
 *@brief 视频列表按钮点击事件回调函数
 */
static void videoList_btn_event_cb(lv_event_t *e)
{
  lv_obj_t *btn = lv_event_get_target(e);
  const char *videoName = (const char *)lv_obj_get_user_data(btn);

  uiCreatePlayWindow(); // 创建播放窗口

  lv_label_set_text(playWindow.videoLabel, videoName);

  if (btn == playingVideoBtn) // 是当前正在播放的视频
    return;

  if (playingVideoBtn != nullptr)
  {
    lv_obj_t *img = lv_obj_get_child(playingVideoBtn, 0);
    lv_img_set_src(img, &item_idle); // 修改上一个播放项目图标
  }

  // 设置视频list播放项目图标icon
  lv_obj_t *img = lv_obj_get_child(btn, 0);
  lv_img_set_src(img, &item_playing);

  playingVideoBtn = btn; // 保存新的视频list btn

  if (uiOpts.playCb != nullptr)
    uiOpts.playCb(videoName); // 新视频播放
}

/**
 *@brief 视频播放底部暂停播放img按钮点击事件回调函数
 */
static void play_window_bottom_pause_btn_click_event_cb(lv_event_t *e)
{
  lv_obj_t *btn = lv_event_get_target(e);

  bool videoState = false;

  if (uiOpts.getStateCb != nullptr)
    videoState = uiOpts.getStateCb();

  videoState = !videoState;

  if (videoState == true)
  {
    if (uiOpts.playCb != nullptr)
      uiOpts.playCb(nullptr); // 传入NULL表示继续播放，而不是新视屏播放
  }
  else
  {
    if (uiOpts.pauseCb != nullptr)
      uiOpts.pauseCb();
  }

  if (clearScreenTimer != nullptr)
    lv_timer_reset(clearScreenTimer); // 重置清屏定时器

  lv_img_set_src(playWindow.pauseImage, videoState ? &playing : &pause_icon);
}

/**
 *@brief 视频播放底部列表img按钮点击事件回调函数
 */
static void play_window_bottom_list_btn_click_event_cb(lv_event_t *e)
{
  if (clearScreenTimer != nullptr)
    lv_timer_del(clearScreenTimer); // 删除清屏定时器

  uiDelPlayWindow(); // 删除播放窗口
}

/**
 *@brief 视频进度滑块条滑动事件函数
 */
static void video_progress_slider_event_cb(lv_event_t *e)
{
  lv_obj_t *slider = lv_event_get_target(e);
  lv_event_code_t e_code = lv_event_get_code(e);

  if (e_code == LV_EVENT_RELEASED)
  {
    videoSliderPressed = false;
    int cur = lv_slider_get_value(slider);

    if (uiOpts.setCurCb != nullptr)
      uiOpts.setCurCb(cur);
  }
  else if (e_code == LV_EVENT_PRESSED)
  {
    videoSliderPressed = true;
  }
  else if (e_code == LV_EVENT_PRESSING)
  {
    if (clearScreenTimer != nullptr)
      lv_timer_reset(clearScreenTimer); // 重置清屏定时器
  }
}

/**
 *@brief 音量进度滑块条滑动事件函数
 */
static void volume_slider_event_cb(lv_event_t *e)
{
  lv_obj_t *slider = lv_event_get_target(e);
  lv_event_code_t e_code = lv_event_get_code(e);

  if (e_code == LV_EVENT_RELEASED)
  {
    int v = lv_slider_get_value(slider);

    if (uiOpts.setVolumeCb != nullptr)
      uiOpts.setVolumeCb(v);
  }
  else if (e_code == LV_EVENT_PRESSING)
  {
    if (clearScreenTimer != nullptr)
      lv_timer_reset(clearScreenTimer); // 重置清屏定时器
  }
}

/**
 *@brief 屏幕点击事件回调函数
 */
static void screen_click_event_handler(lv_event_t *e)
{
  if (playWindow.screen == nullptr)
    return;

  lv_opa_t opa = LV_OPA_50;

  if (lv_obj_get_style_opa(playWindow.bottomCont, LV_PART_MAIN) == LV_OPA_TRANSP)
  {
    // 创建定时器，使底部容器透明
    clearScreenTimer = lv_timer_create(transp_bottom_cont_timer_cb, 3000, nullptr);
    lv_timer_set_repeat_count(clearScreenTimer, 1); // 单次定时器
  }
  else
  {
    opa = LV_OPA_TRANSP;
    if (clearScreenTimer != nullptr)
    {
      lv_timer_del(clearScreenTimer); // 已经透明了，删除定时器
      clearScreenTimer = nullptr;
    }
  }

  lv_obj_set_style_opa(playWindow.bottomCont, opa, LV_STATE_DEFAULT); // 底部容器透明
}

/**
 *@brief  底部容器透明定时器回调函数
 */
static void transp_bottom_cont_timer_cb(lv_timer_t *t)
{
  clearScreenTimer = nullptr;

  lv_obj_set_style_opa(playWindow.bottomCont, LV_OPA_TRANSP, LV_STATE_DEFAULT); // 底部容器透明
}